package com.smart5G.utils;

import com.smart5G.model.Service;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Consumer;

public class DataSimulator {
    //营业厅

    //流量：最大值？聚合？

    //订单：设备都有哪些？订单数量最大值

    public static int size = 5000;

    public static double[][] intensity = new double[size][size];

    public static double down = 21.556014;
    public static double up = 41.919212;
    public static double left = 79.391975;
    public static double right = 121.403694;

    public static class node{
        public Area area;
        public int x;
        public int y;
        public double factor;

        public node(int x, int y, double factor) {
            this.x = x;
            this.y = y;
            this.factor = factor;
        }

        public node(Area area, double factor) {
            this.x = reflectLongitude(area.longitude);
            this.y = reflectLatitude(area.latitude);
            this.factor = factor;
        }
    }

    public static int reflectLatitude(double y){
        return (int)((y-down)/(up-down)*size);
    }

    public static int reflectLongitude(double x){
        return (int)((x-left)/(right-left)*size);
    }

    public static double reflectY(int y){
        double res = y/size*(up-down)+down;
        double cell = (up-down)/size;
        return res+(Math.random()*2-1)*cell;
    }

    public static double reflectX(int x){
        double res = x/size*(right-left)+left;
        double cell = (right-left)/size;
        return res+(Math.random()*2-1)*cell;
    }

    public static List<Area> run(List<com.smart5G.model.Service> serviceList) {
        HashMap<String, Double> hashMap = new HashMap<>();
        hashMap.put("北京市", 100.0);
        hashMap.put("上海市", 100.0);
        hashMap.put("深圳市", 100.0);
        hashMap.put("武汉市", 50.0);
        hashMap.put("成都市", 50.0);
        hashMap.put("西安市", 50.0);
        DataSimulator ds = new DataSimulator();
        List<Area> areaList = new ArrayList<>();
        for (Service service : serviceList) {
            areaList.add(new Area(
                    Integer.parseInt(service.getServiceId()), 0, service.getServiceName(),
                    service.getCity(), Double.parseDouble(service.getLatitude()), Double.parseDouble(service.getLongitude()),
                    service.getCity(), service.getProvince(),
                    hashMap.getOrDefault(service.getCity(), 1.0)
            ));
        }
        double ac = 0;
        for (Area area : areaList) {
            ac += area.factor;
            area.Accumulate = ac;
        }
        for (Area area : areaList) {
            area.Accumulate /= ac;
        }
        return areaList;
    }

    public static void execute(List<node> list){
        Consumer<node> action = node -> AttenuationFunction(node);
        list.stream().forEach(action);
    }

    /**
     * 暂采用普通指数衰减，根据距离计算衰减
     * @param node
     */
    public static void AttenuationFunction(node node){
        double a = 1;
        //处理圆形区域
        int r = size/20;
        for (int i = -r; i < r + 1; i++) {
            for (int j = -r; j < r + 1; j++) {
                double d = Math.sqrt(Math.abs(i*j)*1.0);
                if (d<=r) {
                    intensity[r+i][r+j] += Math.pow(Math.E, -a*d);
                }
            }
        }
    }

    public static HashMap<String, Area> readExcel(){
        HashMap<String, Area> hashMap = new HashMap<>();
        HashMap<Integer, Area> hashMapCode = new HashMap<>();
        try{
            InputStream inputStream = ClassLoader.getSystemResourceAsStream("全国省市区经纬度、区域代码、层级关系.xlsx");
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            XSSFSheet sheetAt = workbook.getSheetAt(0);
            for (Row row : sheetAt) {
                if (row.getRowNum() == 0) {
                    continue;
                }
                if (row.getCell(2).equals("市辖区")){
                    continue;
                }
                Area area = new Area(
                        (int) row.getCell(0).getNumericCellValue(),
                        (int) row.getCell(1).getNumericCellValue(),
                        row.getCell(2)!=null?row.getCell(2).getStringCellValue():"",
                        row.getCell(3)!=null?row.getCell(3).getStringCellValue():"",
                        row.getCell(4)!=null?row.getCell(4).getNumericCellValue():-1,
                        row.getCell(5)!=null?row.getCell(5).getNumericCellValue():-1,
                        0
                );
                DecimalFormat df = new DecimalFormat("#.0000");
                area.latitude = Double.parseDouble(df.format(area.latitude));
                area.longitude = Double.parseDouble(df.format(area.longitude));
                hashMap.put(row.getCell(2).getStringCellValue(), area);
                if (area.code%100==0){
                    hashMapCode.put(area.code, area);
                }
            }
            Iterator<Area> iterator =  hashMap.values().iterator();
            while (iterator.hasNext()) {
                Area area = iterator.next();
                if (!area.parentName.equals("")) {
                    Area parent = hashMap.get(area.parentName);
                    if (!parent.parentName.equals("")) {
                        if (parent.name.equals("市辖区")){
                            Area gp = hashMapCode.get(area.code/100*100);
                            area.province = gp.parentName;
                        }else {
                            Area gp = hashMap.get(parent.parentName);
                            area.province = gp.name;
                        }
                        area.city = parent.name;
                    }else {
                        area.province = area.parentName;
                        area.city = area.name;
                    }
                }else {
                    area.city = area.name;
                    area.province = area.name;
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return hashMap;
    }

    public static class Area{
        public int code;
        public int parentCode;
        public String name;
        public String parentName;
        public double latitude;
        public double longitude;
        public String city;
        public String province;
        public double factor = 10;
        public double Accumulate = 0;

        public Area(int code, int parentCode, String name, String parentName, double latitude, double longitude, double factor) {
            this.code = code;
            this.parentCode = parentCode;
            this.name = name;
            this.parentName = parentName;
            this.latitude = latitude;
            this.longitude = longitude;
            this.factor = factor;
        }

        public Area(int code, int parentCode, String name, String parentName, double latitude, double longitude, String city, String province, double factor) {
            this.code = code;
            this.parentCode = parentCode;
            this.name = name;
            this.parentName = parentName;
            this.latitude = latitude;
            this.longitude = longitude;
            this.city = city;
            this.province = province;
            this.factor = factor;
        }
    }

}